using System;
using System.IO;
using System.Reflection;
using System.Threading;

using Jack.EntityFrameworkCore.WebAPITest.Dapper.Logging;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;

using MySqlConnector;
using MySqlConnector.Logging;

using Swashbuckle.AspNetCore.SwaggerUI;

namespace Jack.EntityFrameworkCore.WebAPITest
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddJackDbContext<Entities.DemoDbContext>(options =>
            {
                MySqlConnectionStringBuilder mySqlConnectionStringBuilder = new MySqlConnectionStringBuilder();
                mySqlConnectionStringBuilder.Server = "127.0.0.1";
                mySqlConnectionStringBuilder.Port = 3306;
                mySqlConnectionStringBuilder.Database = "demo_db";
                mySqlConnectionStringBuilder.UserID = "root";
                mySqlConnectionStringBuilder.Password = "change_me";
                mySqlConnectionStringBuilder.AllowUserVariables = true;
                mySqlConnectionStringBuilder.SslMode = MySqlSslMode.None;
                mySqlConnectionStringBuilder.CharacterSet = "UTF8";
                mySqlConnectionStringBuilder.Pooling = true;
                mySqlConnectionStringBuilder.MaximumPoolSize = 200;
                mySqlConnectionStringBuilder.MinimumPoolSize = 50;
                mySqlConnectionStringBuilder.LoadBalance = MySqlLoadBalance.RoundRobin;
                mySqlConnectionStringBuilder.Pipelining = true;
                mySqlConnectionStringBuilder.UseCompression = true;
                mySqlConnectionStringBuilder.UseXaTransactions = true;

                string connStr = mySqlConnectionStringBuilder.ConnectionString;
                Console.WriteLine(connStr);
                //string connStr = "server=127.0.0.1;Database=demo_db;Uid=root;Pwd=change_me;Port=3306;Allow User Variables=True;SslMode=None;CharSet=UTF8;Pooling=True;ConnectionLifeTime=60;";
                options.UseMySql(connStr, ServerVersion.AutoDetect(connStr), mySqlOptions =>
                {
                    mySqlOptions.CommandTimeout(3);
                    mySqlOptions.MaxBatchSize(50);
                });
            }, new JackDbContextOptions { AddDefaultLogger = true, AddDefaultRepository = true });
            services.AddDbConnectionFactoryWithCtx<Entities.DemoDbContext>(sp => sp.GetRequiredService<Entities.DemoDbContext>().Database.GetDbConnection(), config =>
            {
                config.LogLevel = LogLevel.Information;
                config.LogSensitiveData = true;
                config.ConnectionProjector = conn => conn.ConnectionString;

                return config;
            });

            services.AddSwaggerGen(setup =>
            {
                OpenApiInfo info = new OpenApiInfo
                {
                    Title = "{标题}",
                    Version = "v1",
                    Description = "描述",
                    TermsOfService = new Uri(Assembly.GetEntryAssembly()!.ManifestModule.Name.Replace(".dll", ""), UriKind.Relative)
                };

                setup.SwaggerDoc(info.Version, info);

                string[] files = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
                string[] array = files;
                foreach (string filePath in array)
                {
                    setup.IncludeXmlComments(filePath, includeControllerXmlComments: true);
                }
            });

            services.AddControllers().AddControllersAsServices();
            ThreadPool.SetMinThreads(300, 300);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            MySqlConnectorLogManager.Provider = new MicrosoftExtensionsLoggingLoggerProvider(app.ApplicationServices.GetRequiredService<ILoggerFactory>(), true);

            if (env.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI(delegate (SwaggerUIOptions c)
                {
                    c.SwaggerEndpoint("/swagger/v1/swagger.yaml", "{标题} API V1");
                });

                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

/*
docker pull mysql:5.7
docker volume create --name=mysqldata
docker run -d --name mysql_jack --restart=always -v mysqldata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=change_me -p 3306:3306 -p 33060:33060 --security-opt=seccomp:unconfined --privileged mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --innodb-rollback-on-timeout=ON

CREATE DATABASE `demo_db` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';

CREATE TABLE `user` (
  `Id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `UserName` varchar(255) DEFAULT NULL,
  `Age` int(11) DEFAULT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户';
*/
